<script setup lang="ts">
import type { AttachmentsProps, BubbleListProps, ConversationsProps, PromptsProps, BubbleProps } from 'ant-design-x-vue'
import { Sender, Bubble, Prompts, Welcome, useXAgent, XStream, useXChat } from 'ant-design-x-vue'
import { CloudUploadOutlined, CommentOutlined, EllipsisOutlined, FireOutlined, HeartOutlined, PaperClipOutlined, PlusOutlined, ReadOutlined, ShareAltOutlined, SmileOutlined } from '@ant-design/icons-vue'
import markdownit from 'markdown-it'
import { Badge, Button, Flex, Space, Typography, Avatar, theme } from 'ant-design-vue'
const { token } = theme.useToken()

const styles = computed(() => {
  return {
    layout: {
      width: '100%',
      'min-width': '970px',
      height: '100%',
      'border-radius': `${token.value.borderRadius}px`,
      display: 'flex',
      background: `${token.value.colorBgContainer}`,
      'font-family': `AlibabaPuHuiTi, ${token.value.fontFamily}, sans-serif`
    },
    menu: {
      background: `${token.value.colorBgLayout}80`,
      width: '280px',
      height: '100%',
      display: 'flex',
      'flex-direction': 'column'
    },
    conversations: {
      padding: '0 12px',
      flex: 1,
      'overflow-y': 'auto'
    },
    chat: {
      height: '100%',
      width: '100%',
      'max-width': '700px',
      margin: '0 auto',
      'box-sizing': 'border-box',
      display: 'flex',
      'flex-direction': 'column',
      padding: `${token.value.paddingLG}px`,
      gap: '16px'
    },
    messages: {
      flex: 1
    },
    placeholder: {
      'padding-top': '32px',
      'text-align': 'left',
      flex: 1
    },
    sender: {
      'box-shadow': token.value.boxShadow
    },
    logo: {
      display: 'flex',
      height: '72px',
      'align-items': 'center',
      'justify-content': 'start',
      padding: '0 24px 0 12px',
      'box-sizing': 'border-box'
    },
    'logo-img': {
      width: '24px',
      height: '24px',
      display: 'inline-block'
    },
    'logo-span': {
      display: 'inline-block',
      'font-weight': 'bold',
      color: token.value.colorText,
      'font-size': '16px'
    },
    addBtn: {
      background: '#1677ff0f',
      border: '1px solid #1677ff34',
      width: 'calc(100% - 24px)',
      margin: '0 12px 24px 12px'
    },
    name: {
      'font-size': '14px',
      'text-align': 'left',
      color: token.value.colorText
    }
  } as const
})
// state
const agentRequestLoading = computed(() => {
  return agent.value.isRequesting()
})
const headerOpen = ref(false)

// ======================================= 消息列表 =======================================
const md = markdownit({ html: true, breaks: true })
const roles: BubbleListProps['roles'] = {
  ai: {
    placement: 'start',
    typing: { step: 5, interval: 200000 },
    style: {
      maxWidth: '600px'
    }
  },
  local: {
    placement: 'end',
    variant: 'shadow'
  }
}

function renderTitle(icon: VNode, title: string) {
  return h(Space, { align: 'start' }, () => [icon, h('span', title)])
}
const onPromptsItemClick: PromptsProps['onItemClick'] = (info) => {
  onRequest(info.data.description as string)
}
const placeholderPromptsItems: PromptsProps['items'] = [
  {
    key: '1',
    label: renderTitle(h(FireOutlined, { style: { color: '#FF4D4F' } }), '热门话题'),
    description: '你对什么感兴趣?',
    children: [
      {
        key: '1-1',
        description: `县链云仓是什么?`
      },
      {
        key: '1-2',
        description: `县链科技做什么?`
      },
      {
        key: '1-3',
        description: `县链云仓平台有哪些功能?`
      }
    ]
  },
  {
    key: '2',
    label: renderTitle(h(ReadOutlined, { style: { color: '#1890FF' } }), '设计指导'),
    description: '更好的了解县链模式',
    children: [
      {
        key: '2-1',
        icon: h(HeartOutlined),
        description: `如何成为县域合伙人？`
      },
      {
        key: '2-2',
        icon: h(SmileOutlined),
        description: `如何入驻县链云仓？`
      },
      {
        key: '2-3',
        icon: h(CommentOutlined),
        description: `县链云仓如何收益？`
      }
    ]
  }
]
const placeholderNode = computed(() =>
  h(Space, { direction: 'vertical', size: 16, style: styles.value.placeholder }, () => [
    h(Welcome, {
      variant: 'borderless',
      icon: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp',
      title: '你好, 我是县链云仓AI智能助手',
      description: '做中国最值得信赖的县域经济综合服务商'
    }),
    h(Prompts, {
      title: '你想做什么?',
      items: placeholderPromptsItems,
      styles: {
        list: {
          width: '100%'
        },
        item: {
          flex: 1
        }
      },
      onItemClick: onPromptsItemClick
    })
  ])
)
const items = computed(() => {
  if (messages.value.length === 0) {
    return [{ content: placeholderNode, variant: 'borderless', key: 'placeholder', role: 'ai' }]
  }
  return messages.value.map(({ id, message, status }) => {
    return {
      key: id,
      role: status === 'local' ? 'local' : 'ai',
      content: message
    }
  })
})

// 获取消息
let currentOutput = ''
const [agent] = useXAgent({
  request: ({ message }, { onUpdate, onSuccess }) => {
    fetch('https://wss.lke.cloud.tencent.com/v1/qbot/chat/sse', {
      method: 'POST',
      body: JSON.stringify({
        content: message,
        session_id: 'test-session',
        bot_app_key: 'yakWpwJNxbVzFDKsDZYLxtOiNwKdkRBkEalKNqECNPHFpTGdTkpilyMEcJzLqcBSCKqTayEHtNspomfGIlxEDqWjaEBLhLXzclxxQPdnJEayqoKFnLvgBIFsnWMgQTrK',
        visitor_biz_id: 'test-visitor',
        incremental: true
      })
    })
      .then(async (res) => {
        if (!res.ok) {
          throw new Error(`HTTP error! status: ${res.status}`)
        }
        if (!res.body) {
          throw new Error('Response body is null')
        }
        for await (const chunk of XStream({
          readableStream: res.body
        })) {
          const data = JSON.parse(chunk.data)
          if (data.type === 'reply' && data.payload.is_from_self === false) {
            currentOutput += data.payload.content
            onUpdate(currentOutput)
            if (data.payload.is_final === true) {
              onSuccess([currentOutput])
              currentOutput = ''
            }
          }
        }
      })
      .catch((error) => {
        console.error('Error fetching data:', error)
        onSuccess([])
      })
  }
})

// 数据管理
const { onRequest, messages } = useXChat({
  agent: agent.value
})

// ======================================= 输入框 =======================================
const content = ref('')
// const agentRequestLoading = ref(false)
const attachedFiles = ref<AttachmentsProps['items']>([])
function onSubmit(nextContent: string) {
  if (!nextContent.trim()) return
  onRequest(nextContent)
  content.value = ''
}
function onCancel() {
  content.value = ''
  agentRequestLoading.value = false
}
</script>
<template>
  <div :style="styles.layout">
    <div :style="styles.chat">
      <!-- 🌟 消息列表 -->
      <Bubble.List :items="items" :typing="{ step: 2, interval: 50 }" :roles="roles" :style="styles.messages">
        <!-- <template #header="{ item }">
          <span :style="styles.name">{{ item.from_name }}</span>
        </template>
        <template #avatar="{ item }">
          <Avatar :src="item.from_avatar" size="large" />
        </template> -->
        <template #message="{ item }">
          <template v-if="item.key === 'placeholder'">
            <Bubble :content="item.content" variant="borderless" />
          </template>
          <div v-html="md.render(item.content)" v-else></div>
        </template>
      </Bubble.List>
      <!-- 输入框 -->
      <Sender :value="content" :style="styles.sender" :loading="agentRequestLoading" @submit="onSubmit" @change="(value) => (content = value)" @cancel="onCancel">
        <!-- <template #prefix>
          <Badge :dot="attachedFiles.length > 0 && !headerOpen">
            <Button type="text" @click="() => (headerOpen = !headerOpen)">
              <template #icon>
                <PaperClipOutlined />
              </template>
            </Button>
          </Badge>
        </template> -->
      </Sender>
    </div>
  </div>
</template>
